package com.learning.spring.ioc.bean.annotation;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * ClassName: AnnotationConfig
 * Description:
 * Date: 2018/8/5 14:28 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class AnnotationConfig {

    public static void main(String[] args) {
//        test();
//        test3();
//        testLazy();
        test4();
    }

    /**
     * 注解实现 Bean 的配置：需要配置注解的Bean的扫描器：<context:component-scan base-package="com.learning.spring.ioc.bean">
     * 4个定义Bean的注解： @Component，@Service、@Repository、@Controller 三个内部组合了 @Component
     * 依赖注入的注解：标注在属性或者setXXX方法都生效
     * 1、@javax.annotation.Resource：默认按名字属性，如果属性为空，指定采用变量名或者方法名
     * 2、@org.springframework.beans.factory.annotation.Autowired：默认按类型，如果要使用按名字，需要添加注解 @Qualifier(value = "名字")
     * 3、Autowired 支持Spring4X的泛型的注入，集合标注等，功能更强大
     */
    static void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");

        AnnotationBean annotationBean = context.getBean("annotationBean", AnnotationBean.class);
        annotationBean.done();
        /*
            AnnotationInjectionBean 被实例化了
            调用了 AnnotationInjectionBean.done() 方法
         */
    }

    /**
     * 注解的Bean的扫描器：<context:component-scan>
     * 1、base-package：标注基本的需要扫描的路径，默认是该路径下全部的
     * 2、resource-pattern：对base-package路径下进行过滤，默认是基类包中的所有类，其值为 "**\\/*.class"
     * 3、use-default-filters：默认 true，表示默认会对标注了 @Component，@Service、@Repository、@Controller 的Bean 进行扫描。
     * 如需要使用 context:include-filter ，需要设置默认的这个属性为 false
     * <p>
     * 4、include-filter：要包含的目标类；exclude-filter：要排除的目标类。都可以设置多个，先排除，再包含
     * type 属性：
     * - annotation：标注了 XXannotation 的类
     * - assignable：标记继承扩展类
     * - aspectj：采用 aspectj 表达式
     * - regex：正则表达式
     * - custom：自定义实现，必须实现 org.springframework.core.type.filter.TypeFilter 接口
     * resource属性：
     */
    static void test2() {
    }

    /**
     * 注解实现依赖注入：对集合进行标注
     */
    static void test3() {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");

        AnnotationBean annotationBean = context.getBean("annotationBean", AnnotationBean.class);
        System.out.println(annotationBean.getList());
        System.out.println(annotationBean.getMap());

        /*
        AnnotationInjectionBean 被实例化了
        AnnotationInjectionBean2 被实例化了
        [com.learning.spring.ioc.bean.annotation.AnnotationInjectionBean@5427c60c, com.learning.spring.ioc.bean.annotation.AnnotationInjectionBean2@15bfd87]
        {injectionBean=com.learning.spring.ioc.bean.annotation.AnnotationInjectionBean@5427c60c, injectionBean2=com.learning.spring.ioc.bean.annotation.AnnotationInjectionBean2@15bfd87}
         */
    }

    /**
     * 对延迟依赖的支持：@Lazy
     * 在容器启动的时候，对于 Bean 上面标注了 @Lazy、@Autowired注解的属性，不会立即注入属性值，而是延迟到调用此属性的时候才会注入属性值
     * 注意：@Lazy 必须标注在属性及目标 Bean 上
     */
    static void testLazy() {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");

    }

    /**
     * Bean 的作用范围及生过程方法
     * 作用范围：@Scope
     * 生命过程方法：@PostConstruct、@PreDestroy
     */
    static void test4() {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
        AnnotationBean annotationBean = context.getBean("annotationBean", AnnotationBean.class);
        annotationBean.done();

        ((ClassPathXmlApplicationContext) context).close();

        /*

            AnnotationInjectionBean 被实例化了
            AnnotationInjectionBean2 被实例化了
            AnnotationInjectionBean3 被实例化了
            @PostConstruct 注解标注初始化方法
            调用了 AnnotationInjectionBean.done() 方法
            @PreDestroy 注解标注销毁方法
        */
    }


}
